home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / MONMOVE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  25KB  |  890 lines

  1. /*    SCCS Id: @(#)monmove.c    3.0    89/11/21
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #ifndef LINT    /* comment line for pre-compiled headers */
  6. # ifndef __STDC__    /* comment line for pre-compiled headers */
  7. #define TRAP_H    /* comment line for pre-compiled headers */
  8. /* block some unused #defines to avoid overloading some cpp's */
  9. # endif    /* comment line for pre-compiled headers */
  10. #endif    /* comment line for pre-compiled headers */
  11.  
  12. #include "hack.h"
  13. #include "mfndpos.h"
  14. #ifdef NAMED_ITEMS
  15. #  include "artifact.h"
  16. #endif
  17.  
  18. #ifdef OVL1
  19. static void FDECL(distfleeck,(struct monst *,int *,int *,int *));
  20. #endif /* OVL1 */
  21.  
  22. #ifdef OVL0
  23. # ifdef POLYSELF
  24. static boolean FDECL(itsstuck,(struct monst *));
  25. # endif
  26. #endif /* OVL0 */
  27.  
  28. #ifdef OVLB
  29.  
  30. boolean /* TRUE : mtmp died */
  31. mb_trapped(mtmp)
  32. register struct monst *mtmp;
  33. {
  34.     if (flags.verbose) {
  35.         if (cansee(mtmp->mx, mtmp->my))
  36.            pline("KABOOM!!  You see a door explode.");
  37.         else if (flags.soundok)
  38.                You("hear a distant explosion.");
  39.     }
  40.     mtmp->mstun = 1;
  41.     mtmp->mhp -= rnd(15);
  42.     if(mtmp->mhp <= 0) {
  43.         mondied(mtmp);
  44.         return(TRUE);
  45.     }
  46.     return(FALSE);
  47. }
  48.  
  49. boolean  
  50. mdig_tunnel(mtmp)  /* FALSE: monster died */
  51. register struct monst *mtmp;
  52. {
  53.     register struct rm *here;
  54.     register int pile = rnd(12);
  55.     boolean canseeit = cansee(mtmp->mx, mtmp->my);
  56.     here = &levl[mtmp->mx][mtmp->my];
  57.  
  58.     if (here->typ == SDOOR)
  59.         here->typ = DOOR;
  60.     if(IS_ROCK(here->typ)) {
  61.         /* Just ate something. */
  62.         if(IS_WALL(here->typ)) {
  63.         if (!(here->diggable & W_NONDIGGABLE)) {
  64.             if(flags.soundok && flags.verbose && !rn2(5))
  65.                        You("hear the sound of crashing rock.");
  66.             if(!is_maze_lev) {
  67.                   here->typ = DOOR;
  68.                   here->doormask = D_NODOOR;
  69.             }
  70.             else
  71.                   here->typ = ROOM;
  72.         }
  73.         } else    
  74.             here->typ = CORR;
  75.         mnewsym(mtmp->mx, mtmp->my);
  76.     } else         /* Eats away door if present & closed or locked */
  77.         if(closed_door(mtmp->mx, mtmp->my)) {
  78.             if(here->doormask & D_TRAPPED) {
  79.                     here->doormask = D_NODOOR;
  80.                     if(mb_trapped(mtmp)) return(FALSE);
  81.             } else {
  82.                     if(!rn2(3) && flags.verbose)
  83.                     /* not too often.. */
  84.                         You("feel an unexpected draft of air.");
  85.                     here->doormask = D_BROKEN;
  86.             }
  87.                 mnewsym(mtmp->mx, mtmp->my);
  88.             } else 
  89.             /* it doesn't leave rocks if it didn't dig */
  90.             return TRUE; 
  91.  
  92.     /* Left behind a pile? */
  93.     if(pile < 5) {
  94.         if(pile == 1)
  95.         (void) mksobj_at(BOULDER, mtmp->mx, mtmp->my);
  96.         else
  97.         (void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
  98.     }
  99.     here->seen = TRUE; /* required for newsym and mnewsym to work */
  100.     if(canseeit && mtmp->minvis && !See_invisible)
  101.         newsym(mtmp->mx,mtmp->my);
  102.     else
  103.         mnewsym(mtmp->mx,mtmp->my);
  104.     if (!canseeit)
  105.         here->seen = FALSE;
  106.     return(TRUE);
  107. }
  108.  
  109. #endif /* OVLB */
  110. #ifdef OVL1
  111.  
  112. int
  113. dochugw(mtmp)
  114.     register struct monst *mtmp;
  115. {
  116.     register int x = mtmp->mx;
  117.     register int y = mtmp->my;
  118.     register int rd = dochug(mtmp);
  119.     register int dd;
  120.  
  121.     if(!rd && !mtmp->mpeaceful &&
  122.             (dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) &&
  123.             dd < 100 && !canseemon(mtmp)) {
  124. #ifdef NAMED_ITEMS
  125.         /* Note: this assumes we only want to warn against the monster which
  126.          * the weapon does extra damage to, as there is no "monster which
  127.          * the weapon warns against" field.
  128.          */
  129.         if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1))
  130.             warnlevel = 100;
  131.         else
  132. #endif
  133.         if (Warning && mtmp->m_lev > warnlevel)
  134.             warnlevel = mtmp->m_lev;
  135.     }
  136.     return(rd);
  137. }
  138.  
  139. #endif /* OVL1 */
  140. #ifdef OVL2
  141.  
  142. boolean
  143. onscary(x, y, mtmp)
  144. int x, y;
  145. struct monst *mtmp;
  146. {
  147.     /* Note: minotaurs must be immune to scare monster to avoid abuse
  148.      * from creating them and taking their wands, then polymorphing 60
  149.      * or so wands to get wishing...
  150.      */
  151.     if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
  152.             mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful ||
  153.             mtmp->data == &mons[PM_MINOTAUR])
  154.         return(FALSE);
  155.     return(
  156. #ifdef ELBERETH
  157.            sengr_at("Elbereth", x, y) ||
  158. #endif
  159.             sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0);
  160. }
  161.  
  162. #endif /* OVL2 */
  163. #ifdef OVL1
  164.  
  165. static void
  166. distfleeck(mtmp,inrange,nearby,scared)
  167. register struct monst *mtmp;
  168. int *inrange, *nearby, *scared;
  169. {
  170.     int seescaryx, seescaryy;
  171.  
  172.     *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
  173.                             (BOLT_LIM * BOLT_LIM));
  174.     *nearby = monnear(mtmp, mtmp->mux, mtmp->muy);
  175.  
  176.     /* Note: if your image is displaced, the monster sees the Elbereth
  177.      * at your displaced position, thus never attacking your displaced
  178.      * position, but possibly attacking you by accident.  If you are
  179.      * invisible, it sees the Elbereth at your real position, thus never
  180.      * running into you by accident but possibly attacking the spot
  181.      * where it guesses you are.
  182.      */
  183.     if (Invis && !perceives(mtmp->data)) {
  184.         seescaryx = mtmp->mux;
  185.         seescaryy = mtmp->muy;
  186.     } else {
  187.         seescaryx = u.ux;
  188.         seescaryy = u.uy;
  189.     }
  190.     *scared = (*nearby && onscary(seescaryx, seescaryy, mtmp));
  191.  
  192.     if(*scared && !mtmp->mflee) {
  193. #ifdef POLYSELF
  194.         if (!sticks(uasmon))
  195. #endif
  196.             unstuck(mtmp);    /* monster lets go when fleeing */
  197.         mtmp->mflee = 1;
  198. #ifdef STUPID
  199.         if (rn2(7))
  200.             mtmp->mfleetim = rnd(10);
  201.         else
  202.             mtmp->mfleetim = rnd(100);
  203. #else
  204.         mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
  205. #endif
  206.     }
  207.  
  208. }
  209.  
  210. /* returns 1 if monster died moving, 0 otherwise */
  211. int
  212. dochug(mtmp)
  213. register struct monst *mtmp;
  214. {
  215.     register struct permonst *mdat = mtmp->data;
  216.     register int tmp=0;
  217.     int inrange, nearby, scared;
  218.  
  219. /*    Pre-movement adjustments    */
  220.  
  221.     if(mtmp->cham && !rn2(6))    /* polymorph chameleons */
  222.         (void) newcham(mtmp, (struct permonst *)0);
  223.  
  224.     /* regenerate monsters */
  225.     if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax)
  226.         mtmp->mhp++;
  227.     if(mtmp->mspec_used) mtmp->mspec_used--;
  228.  
  229.     /* polymorph lycanthropes */
  230.     were_change(mtmp);
  231.  
  232.     if(!mtmp->mcanmove) {
  233.         if (Hallucination) pmon(mtmp);
  234.         return(0);    /* frozen monsters don't do anything */
  235.     }
  236.  
  237.     if(mtmp->msleep)    /* there is a chance we will wake it */
  238.         if(!disturb(mtmp)) return(0);
  239.  
  240.     /* not frozen or sleeping: wipe out texts written in the dust */
  241.     wipe_engr_at(mtmp->mx, mtmp->my, 1);
  242.  
  243.     /* confused monsters get unconfused with small probability */
  244.     if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
  245.  
  246.     /* stunned monsters get un-stunned with larger probability */
  247.     if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
  248.  
  249.     /* some monsters teleport */
  250.     if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) {
  251.         rloc(mtmp);
  252.         return(0);
  253.     }
  254.     if(mdat->mmove < rnd(6)) return(0);
  255.  
  256.     /* fleeing monsters might regain courage */
  257.     if(mtmp->mflee && !mtmp->mfleetim
  258.        && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
  259.  
  260.     set_apparxy(mtmp);
  261.     /* Must be done after you move and before the monster does.  The
  262.      * set_apparxy() call in m_move() doesn't suffice since the variables
  263.      * inrange, etc... all depend on stuff set by set_apparxy().
  264.      */
  265.  
  266.     /* The Wizard's prime directive */
  267.     /* may teleport, so do it before inrange is set */
  268.     if(mtmp->iswiz)
  269.         (void) wiz_get_amulet(mtmp);
  270.  
  271.     /* check distance and scariness of attacks */
  272.     distfleeck(mtmp,&inrange,&nearby,&scared);
  273.  
  274. #ifdef INFERNO        /* Demonic Blackmail! */
  275.     if(nearby && mdat->msound == MS_BRIBE &&
  276.        mtmp->mpeaceful && !mtmp->mtame) {
  277.         if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
  278.             pline("%s whispers something to thin air.",
  279.                 cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
  280. # ifdef POLYSELF
  281.             if (is_demon(uasmon)) rloc(mtmp);
  282.               /* "Good hunting, brother" */
  283.             else {
  284. # endif
  285.                 mtmp->minvis = 0;
  286.                 /* Why?  For the same reason in real demon talk */
  287.                 pline("%s gets angry.", Xmonnam(mtmp));
  288.                 mtmp->mpeaceful = 0;
  289.                 /* since no way is an image going to pay it off */
  290. # ifdef POLYSELF
  291.             }
  292. # endif
  293.         } else if(demon_talk(mtmp)) return(1);    /* you paid it off */
  294.     }
  295. #endif
  296.  
  297. /*    Now the actual movement phase    */
  298.  
  299.     if(!nearby || mtmp->mflee || scared ||
  300.        mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
  301.        (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
  302.        (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
  303.        (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
  304.  
  305.         tmp = m_move(mtmp, 0);
  306.         distfleeck(mtmp,&inrange,&nearby,&scared);    /* recalc */
  307.  
  308.         switch (tmp) {
  309.  
  310.             case 0:    /* no movement, but it can still attack you */
  311.             case 3:    /* absolutely no movement */
  312.                 /* for pets, case 0 and 3 are equivalent */
  313.              /* During hallucination, monster appearance should
  314.               * still change - even if it doesn't move.
  315.                */
  316.              if(Hallucination) pmon(mtmp);
  317.              break;
  318.              case 1:    /* monster moved */
  319.             /* Maybe it stepped on a trap and fell asleep... */
  320.             if(mtmp->msleep || !mtmp->mcanmove) return(0);
  321.              if(!nearby && ranged_attk(mdat)) break;
  322.              else if(mdat->mmove <= 12) return(0);
  323.              break;
  324.              case 2:    /* monster died */
  325.              return(1);
  326.          }
  327.     }
  328.  
  329. /*    Now, attack the player if possible - one attack set per monst    */
  330.  
  331.     if(inrange && !noattacks(mdat) &&
  332.        !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3)
  333.         if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
  334.  
  335. #ifdef WORM
  336.     if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp);
  337. #endif
  338.  
  339.     /* extra emotional attack for vile monsters */
  340.     if(inrange && mtmp->data->msound == MS_CUSS &&
  341.        !mtmp->minvis && !mtmp->mpeaceful && !rn2(5))
  342.         cuss(mtmp);
  343.  
  344.     /* extra movement for fast monsters */
  345.     if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1);
  346.     return(tmp == 2);
  347. }
  348.  
  349. static const char NEARDATA practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 };
  350. static const char NEARDATA magical[] = {
  351.     AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM,
  352. #ifdef SPELLS
  353.     SPBOOK_SYM,
  354. #endif
  355.     0 };
  356. static const char NEARDATA indigestion[] = { BALL_SYM, ROCK_SYM, 0 };
  357.  
  358. #endif /* OVL1 */
  359. #ifdef OVL0
  360.  
  361. #ifdef POLYSELF
  362. static boolean
  363. itsstuck(mtmp)
  364. register struct monst *mtmp;
  365. {
  366.     if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) {
  367.         kludge("%s cannot escape from you!", Monnam(mtmp));
  368.         return(TRUE);
  369.     }
  370.     return(FALSE);
  371. }
  372. #endif
  373.  
  374. int
  375. m_move(mtmp, after)
  376. register struct monst *mtmp;
  377. register int after;
  378. {
  379.     register struct monst *mtmp2;
  380.     register int nx,ny,omx,omy,appr,nearer,cnt,i,j;
  381.     xchar gx,gy,nix,niy,chcnt;
  382.     schar chi;
  383.     boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
  384.     boolean likerock=0, can_tunnel=0;
  385.     boolean can_open=0, can_unlock=0, doorbuster=0;
  386.     struct permonst *ptr = mtmp->data;
  387.     schar mmoved = 0;    /* not strictly nec.: chi >= 0 will do */
  388.     coord poss[9];
  389.     long info[9];
  390.     long flag;
  391.  
  392.     if(mtmp->mtrapped) {
  393.         i = mintrap(mtmp);
  394.         if(i == 2) return(2);    /* it died */
  395.         if(i == 1) return(0);    /* still in trap, so didn't move */
  396.     }
  397.     if(mtmp->mhide &&
  398.        (OBJ_AT(mtmp->mx, mtmp->my) || levl[mtmp->mx][mtmp->my].gmask) &&
  399.        rn2(10))
  400.         return(0);        /* do not leave hiding place */
  401.     if(mtmp->meating) {
  402.         mtmp->meating--;
  403.         return(3);            /* still eating */
  404.     }
  405.  
  406.     set_apparxy(mtmp);
  407.     /* where does mtmp think you are? */
  408.     /* Not necessary if m_move called from this file, but necessary in
  409.      * other calls of m_move (ex. leprechauns dodging)
  410.      */
  411.     can_tunnel = tunnels(ptr) &&
  412. #ifdef REINCARNATION
  413.              dlevel != rogue_level &&
  414. #endif
  415.              (!needspick(ptr) || m_carrying(mtmp, PICK_AXE));
  416.     can_open = !(nohands(ptr) || verysmall(ptr));
  417.     can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz);
  418.     doorbuster = is_giant(ptr);
  419. #ifdef WORM
  420.     if(mtmp->wormno) goto not_special;
  421. #endif
  422.     /* my dog gets special treatment */
  423.     if(mtmp->mtame) {
  424.         mmoved = dog_move(mtmp, after);
  425.         goto postmov;
  426.     }
  427.  
  428.     /* likewise for shopkeeper */
  429.     if(mtmp->isshk) {
  430.         mmoved = shk_move(mtmp);
  431.         if(mmoved == -2) return(2);
  432.         if(mmoved >= 0) goto postmov;
  433.         mmoved = 0;        /* follow player outside shop */
  434.     }
  435.  
  436.     /* and for the guard */
  437.     if(mtmp->isgd) {
  438.         mmoved = gd_move(mtmp);
  439.         if(mmoved == -2) return(2);
  440.         if(mmoved >= 0) goto postmov;
  441.         mmoved = 0;
  442.     }
  443.  
  444.     /* and the wiz already got special treatment */
  445.     if(mtmp->iswiz) {
  446.         mmoved = 0;
  447.         goto postmov;
  448.     }
  449. #if defined(ALTARS) && defined(THEOLOGY)
  450.     /* and for the priest */
  451.     if(mtmp->ispriest) {
  452.         mmoved = pri_move(mtmp);
  453.         if(mmoved == -2) return(2);
  454.         if(mmoved >= 0) goto postmov;
  455.         mmoved = 0;
  456.     }
  457. #endif
  458. #ifdef MAIL
  459.     if(ptr == &mons[PM_MAIL_DAEMON]) {
  460.         if(flags.soundok && canseemon(mtmp))
  461.         verbalize("I'm late!");
  462.         mongone(mtmp);
  463.         return(2);        
  464.     }
  465. #endif
  466.     /* teleport if that lies in our nature */
  467.     if(ptr == &mons[PM_TENGU] && !rn2(5)) {
  468.         if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
  469.         rloc(mtmp);
  470.         else
  471.         mnexto(mtmp);
  472.         mmoved = 1;
  473.         goto postmov;
  474.     }
  475. #ifdef WORM
  476. not_special:
  477. #endif
  478.     if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
  479.     appr = 1;
  480.     if(mtmp->mflee) appr = -1;
  481.     if(mtmp->mconf || (Invis && !perceives(ptr)) ||  !mtmp->mcansee ||
  482. #ifdef POLYSELF
  483.        (u.usym == S_MIMIC_DEF) || u.uundetected ||
  484. #endif
  485.        (mtmp->mpeaceful && !mtmp->isshk) ||    /* allow shks to follow */
  486.        ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||
  487.          ptr->mlet == S_YLIGHT) && !rn2(3)))
  488.         appr = 0;
  489.     omx = mtmp->mx;
  490.     omy = mtmp->my;
  491.     gx = mtmp->mux;
  492.     gy = mtmp->muy;
  493.     if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold)
  494.         appr = -1;
  495.  
  496.     if(can_track(ptr)) {
  497.         register coord *cp;
  498.         schar mroom;
  499.  
  500.         mroom = inroom(omx,omy);
  501.         if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
  502.         cp = gettrack(omx,omy);
  503.         if(cp){
  504.             gx = cp->x;
  505.             gy = cp->y;
  506.         }
  507.         }
  508.     }
  509.  
  510. #ifdef REINCARNATION
  511.     if (dlevel != rogue_level)
  512. #endif
  513.     {
  514.         register int pctload = (curr_mon_load(mtmp) * 100) /
  515.             max_mon_load(mtmp);
  516.  
  517.         /* look for gold or jewels nearby */
  518.         likegold = (likes_gold(ptr) && pctload < 95);
  519.         likegems = (likes_gems(ptr) && pctload < 85);
  520.         likeobjs = (likes_objs(ptr) && pctload < 75);
  521.         likemagic = (likes_magic(ptr) && pctload < 85);
  522.         likerock = (throws_rocks(ptr) && pctload < 50);
  523.         conceals = hides_under(ptr);
  524.     }
  525.  
  526. #define SQSRCHRADIUS    5
  527. #define    SRCHRADIUS    (SQSRCHRADIUS*SQSRCHRADIUS)
  528.  
  529.       { xchar mind = SRCHRADIUS;        /* not too far away */
  530.     register int dd;
  531.  
  532.     /* cut down the search radius if it thinks character is closer. */
  533.     if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS &&
  534.         !mtmp->mtame && !mtmp->mpeaceful)     mind /= 2;
  535.  
  536.     if(likegold){
  537.         register struct gold *gold;
  538.  
  539.         for(gold = fgold; gold; gold = gold->ngold)
  540.         if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){
  541.             mind = dd;
  542.             gx = gold->gx;
  543.             gy = gold->gy;
  544.         }
  545.     }
  546.     if((likegems || likeobjs || likemagic || likerock || conceals)
  547.           && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) {
  548.         register struct obj *otmp;
  549.         register int xx, yy;
  550.  
  551.         for(xx = omx-SQSRCHRADIUS; xx <= omx+SQSRCHRADIUS; xx++) {
  552.         for(yy = omy-SQSRCHRADIUS; yy <= omy+SQSRCHRADIUS; yy++) {
  553.             if(!isok(xx, yy)) continue;
  554.             if((dd = dist2(omx,omy,xx, yy)) >= mind) continue;
  555.             for(otmp = level.objects[xx][yy]; otmp; otmp = otmp->nexthere)
  556.               if((likeobjs && index(practical, otmp->olet)) ||
  557.              (likemagic && index(magical, otmp->olet)) ||
  558.              (likerock && otmp->otyp == BOULDER) ||
  559.              (likegems && otmp->olet == GEM_SYM &&
  560.               otmp->otyp < LAST_GEM + 6) ||
  561.              (conceals && !cansee(otmp->ox,otmp->oy)) ||
  562.              (ptr == &mons[PM_GELATINOUS_CUBE] &&
  563.               !index(indigestion, otmp->olet))
  564.              ) {
  565.               if(can_carry(mtmp,otmp))
  566.                 if(ptr->mlet != S_UNICORN ||
  567.                    objects[otmp->otyp].g_val != 0){
  568.                 mind = dd;
  569.                 gx = otmp->ox;
  570.                 gy = otmp->oy;
  571.                 break;
  572.                 }
  573.               }
  574.         }
  575.         }
  576.     }
  577.     if(mind < SRCHRADIUS && appr == -1) {
  578.         if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) {
  579.         gx = mtmp->mux;
  580.         gy = mtmp->muy;
  581.         } else
  582.         appr = 1;
  583.     }
  584.       }
  585.     nix = omx;
  586.     niy = omy;
  587.     flag = ALLOW_TRAPS;
  588.     if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM);
  589.     else flag |= ALLOW_U;
  590.     if (ptr->mlet == S_UNICORN) flag |= NOTONL;
  591.     if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
  592.     if (can_tunnel) flag |= ALLOW_DIG;
  593.     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
  594.     if (is_undead(ptr)) flag |= NOGARLIC;
  595.     if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
  596.     if (can_open) flag |= OPENDOOR;
  597.     if (can_unlock) flag |= UNLOCKDOOR;
  598.     if (doorbuster) flag |= BUSTDOOR;
  599.     cnt = mfndpos(mtmp, poss, info, flag);
  600.     chcnt = 0;
  601.     chi = -1;
  602.  
  603.     for(i=0; i < cnt; i++) {
  604.         nx = poss[i].x;
  605.         ny = poss[i].y;
  606.  
  607.         if (appr != 0) for(j=0; j < MTSZ && j < cnt-1; j++)
  608.         if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  609.             if(rn2(4*(cnt-j))) goto nxti;
  610.  
  611.         nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy));
  612.  
  613.         if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
  614.                (!appr && !rn2(++chcnt)) || !mmoved) {
  615.         nix = nx;
  616.         niy = ny;
  617.         chi = i;
  618.         mmoved = 1;
  619.         }
  620.     nxti:    ;
  621.     }
  622.  
  623.     if(mmoved) {
  624. #ifdef POLYSELF
  625.         if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
  626.         return(3);
  627. #endif
  628.         if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) {
  629.         mtmp->mux = u.ux;
  630.         mtmp->muy = u.uy;
  631.         return(0);
  632.         }
  633.         /* The monster may attack another based on 1 of 2 conditions:
  634.          * 1 - He may be under the "conflict" influence.
  635.          * 2 - He may mistake the monster for your (displaced) image.
  636.          * Pets get taken care of above and shouldn't reach this code.
  637.          */
  638.         if((info[chi] & ALLOW_M) ||
  639.            (nix == mtmp->mux && niy == mtmp->muy)) {
  640.         int stat;
  641.         mtmp2 = m_at(nix,niy);
  642.         if((stat = mattackm(mtmp, mtmp2)) == 1 && rn2(4) &&
  643.             mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2)
  644.             return(2);
  645.         if(stat == -1) return(2);
  646.         return(3);
  647.         }
  648. #ifdef WORM
  649.         /* The square now has a worm segment and must keep its MON_AT() state */
  650.         if (!mtmp->wormno)
  651. #endif
  652.             remove_monster(omx, omy);
  653.         place_monster(mtmp, nix, niy);
  654.         for(j = MTSZ-1; j > 0; j--)
  655.         mtmp->mtrack[j] = mtmp->mtrack[j-1];
  656.         mtmp->mtrack[0].x = omx;
  657.         mtmp->mtrack[0].y = omy;
  658. #ifdef WORM
  659.         if(mtmp->wormno) worm_move(mtmp);
  660. #endif
  661.     } else {
  662.         if(ptr->mlet == S_UNICORN && rn2(2)) {
  663.         rloc(mtmp);
  664.         return(1);
  665.         }
  666. #ifdef WORM
  667.         if(mtmp->wormno) worm_nomove(mtmp);
  668. #endif
  669.     }
  670. postmov:
  671.     if(mmoved == 1) {
  672.         boolean canseeit = cansee(mtmp->mx, mtmp->my);
  673.         boolean abstain = (mtmp->mpeaceful && !mtmp->mtame);
  674.  
  675.         if(mintrap(mtmp) == 2) return(2);    /* he died */
  676.  
  677.         /* open a door, or crash through it, if you can */
  678.         if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
  679.             && !passes_walls(ptr) /* doesn't need to open doors */
  680.             && !can_tunnel /* taken care of below */
  681.           ) {
  682.         struct rm *here = &levl[mtmp->mx][mtmp->my];
  683.         boolean btrapped = (here->doormask & D_TRAPPED);
  684.  
  685.         if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
  686.             if (flags.verbose && canseeit)
  687.             pline("%s %ss under the door.", Monnam(mtmp),
  688.                   ptr == &mons[PM_FOG_CLOUD] ? "flow" : "ooze");
  689.         } else if(here->doormask & D_LOCKED && can_unlock) {
  690.             if(btrapped) {
  691.             here->doormask = D_NODOOR;
  692.             mnewsym(mtmp->mx, mtmp->my);
  693.             if (canseeit) prl(mtmp->mx,mtmp->my);
  694.             if(mb_trapped(mtmp)) return(2);
  695.             } else {
  696.             if (flags.verbose) {
  697.                 if (canseeit)
  698.                   You("see a door being unlocked and opened.");
  699.                 else if (flags.soundok)
  700.                    You("hear a door being unlocked and opened.");
  701.                 }
  702.                 here->doormask = D_ISOPEN;
  703.             mnewsym(mtmp->mx, mtmp->my);
  704.             if (canseeit) prl(mtmp->mx,mtmp->my);
  705.             }
  706.         } else if (here->doormask == D_CLOSED && can_open) {
  707.             if(btrapped) {
  708.             here->doormask = D_NODOOR;
  709.             mnewsym(mtmp->mx, mtmp->my);
  710.             if (canseeit) prl(mtmp->mx,mtmp->my);
  711.             if(mb_trapped(mtmp)) return(2);
  712.             } else {
  713.                 if (flags.verbose) {
  714.                 if (canseeit)
  715.                      You("see a door being opened.");
  716.                 else if (flags.soundok)
  717.                      You("hear the sound of a door opening.");
  718.                 }
  719.                 here->doormask = D_ISOPEN;
  720.             mnewsym(mtmp->mx, mtmp->my);
  721.             if (canseeit) prl(mtmp->mx,mtmp->my);
  722.             }
  723.         } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
  724.                /* mfndpos guarantees this must be a doorbuster */
  725.             if(btrapped) {
  726.             here->doormask = D_NODOOR;
  727.             mnewsym(mtmp->mx, mtmp->my);
  728.             if (canseeit) prl(mtmp->mx,mtmp->my);
  729.             if(mb_trapped(mtmp)) return(2);
  730.             } else {
  731.                 if (flags.verbose) {
  732.                 if (canseeit)
  733.                     You("see a door crash open.");
  734.                 else if (flags.soundok)
  735.                     You("hear the sound of a door crashing open.");
  736.                 }
  737.                 if (here->doormask & D_LOCKED && !rn2(2))
  738.                     here->doormask = D_NODOOR;
  739.                 else here->doormask = D_BROKEN;
  740.             mnewsym(mtmp->mx, mtmp->my);
  741.             if (canseeit) prl(mtmp->mx,mtmp->my);
  742.             }
  743.         }
  744.           }
  745.         /* Maybe a rock mole just ate something? */
  746.         if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */
  747.  
  748.         if(levl[mtmp->mx][mtmp->my].gmask == TRUE) {
  749.         /* Maybe a rock mole just ate some gold */
  750.         if(metallivorous(ptr)) meatgold(mtmp);
  751.         if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp);
  752.         }
  753.         if(OBJ_AT(mtmp->mx, mtmp->my)) {
  754.         /* Maybe a rock mole just ate some metal object */
  755.         if(metallivorous(ptr)) meatgold(mtmp);
  756.         /* Maybe a cube ate just about anything */
  757.         if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp);
  758.  
  759.         if ((!abstain || !rn2(10)) 
  760.             && (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) {
  761.             if(likeobjs) mpickstuff(mtmp, practical);
  762.             if(likemagic) mpickstuff(mtmp, magical);
  763.             if(likerock || likegems) mpickgems(mtmp);
  764.         }
  765.         }
  766.         if(mtmp->mhide) mtmp->mundetected = (OBJ_AT(mtmp->mx, mtmp->my)
  767.                     || levl[mtmp->mx][mtmp->my].gmask);
  768.  
  769.         /* set also in domove(), hack.c */
  770.         if(u.uswallow && mtmp == u.ustuck) {
  771.         u.ux = mtmp->mx;
  772.         u.uy = mtmp->my;
  773.             if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) {
  774.             swallowed(0);
  775.             newsym(mtmp->mdx,mtmp->mdy);
  776.             mtmp->mdx = mtmp->mx;
  777.             mtmp->mdy = mtmp->my;
  778.         }
  779.         }
  780.         pmon(mtmp);
  781.     }
  782.     return(mmoved);
  783. }
  784.  
  785. #endif /* OVL0 */
  786. #ifdef OVL2
  787.  
  788. boolean
  789. closed_door(x, y)
  790. register int x, y;
  791. {
  792.     return(IS_DOOR(levl[x][y].typ) &&
  793.             (levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
  794. }
  795.  
  796. boolean
  797. accessible(x, y)
  798. register int x, y;
  799. {
  800.     return(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y));
  801. }
  802.  
  803. #endif /* OVL2 */
  804. #ifdef OVL1
  805.  
  806. void
  807. set_apparxy(mtmp)        /* where does mtmp think you are standing? */
  808.     register struct monst *mtmp;
  809. {
  810. #define notseen (Invis && !perceives(mtmp->data))
  811. /*    add cases as required.  eg. Displacement ... */
  812.     register int disp = (notseen ? 1 : Displaced ? 2 : 0);
  813.  
  814. /*     without something like the following, invis. and displ. are too */
  815. /*    powerful. */
  816.     register boolean gotu =
  817.         (notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE);
  818.  
  819. /*    Monsters which know where you are don't suddenly forget, if you
  820.     didn't move away. */
  821.     if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1;
  822.  
  823. /*     your dog follows your smell */
  824.     if(!disp || mtmp->mtame || gotu ||
  825. /*    If invisible but not displaced, staying around gets you 'discovered' */
  826.         (!Displaced && u.dx == 0 && u.dy == 0)) {
  827.         mtmp->mux = u.ux;
  828.         mtmp->muy = u.uy;
  829.     }
  830.     else do {
  831.         mtmp->mux = u.ux - disp + rn2(2*disp+1);
  832.         mtmp->muy = u.uy - disp + rn2(2*disp+1);
  833.     } while((mtmp->mux != u.ux || mtmp->muy != u.uy) &&
  834.             ( (!passes_walls(mtmp->data) &&
  835.               (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) ||
  836.                (closed_door(mtmp->mux, mtmp->muy) &&
  837.             !amorphous(mtmp->data)
  838.                )
  839.               )
  840.           ) ||
  841.           (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my)
  842.             )
  843.            );
  844. }
  845.  
  846. #endif /* OVL1 */
  847. #ifdef OVLB
  848.  
  849. #ifdef STUPID_CPP    /* otherwise these functions are macros in rm.h */
  850. /*
  851.  * Functions for encapsulation of level.monsters references.
  852.  */
  853. boolean
  854. MON_AT(x, y)
  855. int x, y;
  856. {
  857.     return(level.monsters[x][y] != (struct monst *)0);
  858. }
  859.  
  860. void place_monster(mtmp, x, y)
  861. register struct monst *mtmp;
  862. int x, y;
  863. {
  864.     level.monsters[x][y] = mtmp;
  865.     mtmp->mx = x;
  866.     mtmp->my = y;
  867. }
  868.  
  869. void place_worm_seg(mtmp, x, y)
  870. register struct monst *mtmp;
  871. int x, y;
  872. {
  873.     level.monsters[x][y] = mtmp;
  874. }
  875.  
  876. void remove_monster(x, y)
  877. int x, y;
  878. {
  879.     level.monsters[x][y] = (struct monst *)0;
  880. }
  881.  
  882. struct monst *m_at(x, y)
  883. int x, y;
  884. {
  885.     return(level.monsters[x][y]);
  886. }
  887. #endif    /* STUPID_CPP */
  888.  
  889. #endif /* OVLB */
  890.